package com.jack.util;

import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Tuple;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author LiJiakui
 * @ClassName:RedisUtil
 * @Description:
 */
public class RedisUtil {

    private static final Logger logger = LoggerFactory.getLogger(RedisUtil.class);
    /**
     * jedis 连接池
     */
    private static JedisPool jedisPool;

    @Resource
    public void setJedisPool(JedisPool jedisPool) {
        RedisUtil.jedisPool = jedisPool;
    }

    /**
     * 获取连接对象
     *
     * @return ShardedJedis
     * @throws
     * @Title:getShardedJedis
     */
    public static Jedis getJedis() {
        return RedisUtil.jedisPool.getResource();
    }


    /**
     * 根据redis的key找到对应的值
     *
     * @param key redis键
     * @return 返回redis储存信息
     */
    public static String get(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.get(key);
        } catch (Exception e) {
            logger.error("redis get error", e);
            return null;
        }
    }

    /**
     * 设置redis value
     *
     * @param key
     * @param value 1成功 0失败
     * @return
     */
    public static Long setNx(String key, String value) {
        try (Jedis jedis = getJedis()) {
            return jedis.setnx(key, value);
        } catch (Exception e) {
            logger.error("redis setNx error", e);
            return null;
        }
    }

    /**
     * 设置redis value 并设置失效时间
     *
     * @param key
     * @param value
     * @param seconds
     * @return 1成功 0失败
     */
    public static Long setNx(String key, String value, int seconds) {
        Long res = 0L;
        try (Jedis jedis = getJedis()) {
            res = jedis.setnx(key, value);
            if (res.longValue() == 1) {
                jedis.expire(key, seconds);
            }
        } catch (Exception e) {
            logger.error("redis setNx and expire error", e);
        }
        return res;
    }

    /**
     * 设置新值 返回旧值
     *
     * @param key
     * @param value
     * @return
     */
    public static String getSet(String key, String value) {
        try (Jedis jedis = getJedis()) {
            return jedis.getSet(key, value);
        } catch (Exception e) {
            logger.error("redis getSet error", e);
            return null;
        }
    }

    /**
     * 存储redis的键值不设置时间
     *
     * @param key redis键
     * @param value redis值
     */
    public static String set(String key, String value) {
        try (Jedis jedis = getJedis()) {
            return jedis.set(key, value);
        } catch (Exception e) {
            logger.error("redis set error", e);
            return null;
        }
    }

    /**
     * 设置时间存储redis
     *
     * @param key redis键
     * @param value redis值
     * @param seconds  时间(秒)
     */
    public static String setex(String key, String value, int seconds) {
        try (Jedis jedis = getJedis()) {
            return jedis.setex(key, seconds, value);
        } catch (Exception e) {
            logger.error("redis setex error", e);
            return null;
        }
    }

    /**
     * 加入计时器
     *
     * @param key
     * @param seconds
     */
    public static Long expire(String key, int seconds) {
        try (Jedis jedis = getJedis()) {
            return jedis.expire(key, seconds);
        } catch (Exception e) {
            logger.error("redis expire error", e);
            return null;
        }
    }

    /**
     * 根据redis键值删除redis
     *
     * @param key 键值
     */
    public static Long del(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.del(key);
        } catch (Exception e) {
            logger.error("redis del error", e);
            return null;
        }
    }

    /**
     * 在链表头位置插入数据
     *
     * @param key
     * @param value
     * @author LI JIA KUI
     * @date 2017年11月10日 上午6:03:28
     * @see [类、类#方法、类#成员]
     */
    public static Long lpush(String key, String value) {
        try (Jedis jedis = getJedis()) {
            return jedis.lpush(key, value);
        } catch (Exception e) {
            logger.error("redis lpush error", e);
            return null;
        }
    }

    /**
     * 根据key获取链表
     *
     * @param key
     * @param start
     * @param end
     * @return
     * @author LI JIA KUI
     * @date 2017年11月10日 上午6:03:14
     * @see [类、类#方法、类#成员]
     */
    public static List<String> lrange(String key, Long start, Long end) {
        try (Jedis jedis = getJedis()) {
            return jedis.lrange(key, start, end);
        } catch (Exception e) {
            logger.error("redis lrange error", e);
            return null;
        }
    }

    /**
     * 获取链表中的元素的数量
     *
     * @param key
     * @return
     * @author LI JIA KUI
     * @date 2017年11月10日 上午6:02:51
     * @see [类、类#方法、类#成员]
     */
    public static Long llen(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.llen(key);
        } catch (Exception e) {
            logger.error("redis llen error", e);
            return null;
        }
    }


    /**
     * 指定KEY 增加 1
     *
     * @param key
     * @return
     */
    public static Long incr(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.incr(key);
        } catch (Exception e) {
            logger.error("redis incr error", e);
            return null;
        }
    }

    /**
     * 增量操作
     *
     * @param key
     * @param increment
     * @return
     */
    public static Long incrby(String key, long increment) {
        try (Jedis jedis = getJedis()) {
            return jedis.incrBy(key, increment);
        } catch (Exception e) {
            logger.error("redis incrby error", e);
            return null;
        }
    }

    /**
     * zset 增量操作
     *
     * @param key
     * @param score
     * @param member
     */
    public static Double zincrby(String key, double score, String member) {
        try (Jedis jedis = getJedis()) {
            return jedis.zincrby(key, score, member);
        } catch (Exception e) {
            logger.error("redis zincrby error", e);
            return null;
        }
    }

    /**
     * 指定KEY 减 1
     *
     * @param key
     * @return
     */
    public static Long decr(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.decr(key);
        } catch (Exception e) {
            logger.error("redis decr error", e);
            return null;
        }
    }

    public static Set<Tuple> zrevrangeWithScores(String key, int start, int end) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrevrangeWithScores(key, start, end);
        } catch (Exception e) {
            logger.error("redis zrevrangeWithScores error", e);
            return null;
        }
    }

    public static Set<Tuple> zrangeWithScores(String key, int start, int end) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrangeWithScores(key, start, end);
        } catch (Exception e) {
            logger.error("redis zrangeWithScores error", e);
            return null;
        }
    }

    public static Long zadd(String key, double score, String member) {
        try (Jedis jedis = getJedis()) {
            return jedis.zadd(key, score, member);
        } catch (Exception e) {
            logger.error("redis zadd error", e);
            return null;
        }
    }

    public static Long zadd(String key, Map<String, Double> scoreMembers) {
        try (Jedis jedis = getJedis()) {
            return jedis.zadd(key, scoreMembers);
        } catch (Exception e) {
            logger.error("redis zadd error", e);
            return null;
        }
    }

    public static boolean exists(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.exists(key);
        } catch (Exception e) {
            logger.error("redis exists error", e);
            return false;
        }
    }


    public static Long zrank(String key, String member) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrank(key, member);
        } catch (Exception e) {
            logger.error("redis zrank error", e);
            return null;
        }
    }

    public static Long zrevrank(String key, String member) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrevrank(key, member);
        } catch (Exception e) {
            logger.error("redis zrevrank error", e);
            return null;
        }
    }

    public static Double zscore(String key, String member) {
        try (Jedis jedis = getJedis()) {
            return jedis.zscore(key, member);
        } catch (Exception e) {
            logger.error("redis zscore error", e);
            return null;
        }
    }

    /**
     * zSet 删除一个或多个成员
     *
     * @param key
     * @param member
     * @return
     */
    public static Long zrem(String key, String... member) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrem(key, member);
        } catch (Exception e) {
            logger.error("redis zrem error", e);
            return null;
        }
    }

    public static Map<String, String> hgetAll(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.hgetAll(key);
        } catch (Exception e) {
            logger.error("redis hgetAll error", e);
            return null;
        }
    }

    public static Long hdel(String key, String... field) {
        try (Jedis jedis = getJedis()) {
            return jedis.hdel(key, field);
        } catch (Exception e) {
            logger.error("redis hgetAll error", e);
            return null;
        }
    }

    public static String lpop(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.lpop(key);
        } catch (Exception e) {
            logger.error("redis lpop error", e);
            return null;
        }
    }

    public static Long rpush(String key, String... string) {
        try (Jedis jedis = getJedis()) {
            return jedis.rpush(key, string);
        } catch (Exception e) {
            logger.error("redis rpush error", e);
            return null;
        }
    }

    public static Long hincrBy(String key, String actionType, long icrVal) {
        try (Jedis jedis = getJedis()) {
            return jedis.hincrBy(key, actionType, icrVal);
        } catch (Exception e) {
            logger.error("redis rpush error", e);
            return null;
        }
    }

    /**
     * has 进行incr
     *
     * @param key
     * @param field
     * @param value
     * @param seconds
     * @return
     */
    public static Long hincrBy(String key, String field, long value, int seconds) {
        try (Jedis jedis = getJedis()) {
            Long val = jedis.hincrBy(key, field, value);
            if (seconds > 0) {
                jedis.expire(key, seconds);
            }
            return val;
        } catch (Exception e) {
            logger.error("redis hincrBy error", e);
            return null;
        }
    }

    /**
     * hsah中存值
     *
     * @param key
     * @param field
     * @param val
     * @return
     */
    public static Long hset(String key, String field, String val) {
        try (Jedis jedis = getJedis()) {
            return jedis.hset(key, field, val);
        } catch (Exception e) {
            logger.error("redis hset error", e);
            return null;
        }
    }

    /**
     * hsah中存值 并可设置失效时间
     *
     * @param key
     * @param field
     * @param val
     * @param seconds
     * @return
     */
    public static Long hset(String key, String field, String val, int seconds) {
        try (Jedis jedis = getJedis()) {
            Long res = jedis.hset(key, field, val);
            if (seconds > 0) {
                jedis.expire(key, seconds);
            }
            return res;
        } catch (Exception e) {
            logger.error("redis hset error", e);
            return null;
        }
    }

    /**
     * hash 根据field获取value
     *
     * @param key
     * @param field
     * @return
     */
    public static String hget(String key, String field) {
        try (Jedis jedis = getJedis()) {
            return jedis.hget(key, field);
        } catch (Exception e) {
            logger.error("redis hget error", e);
            return null;
        }
    }

    /**
     * sorted set 元素个数
     *
     * @param key
     * @return
     */
    public static Long zcard(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.zcard(key);
        } catch (Exception e) {
            logger.error("redis zcard error", e);
            return null;
        }
    }

    public static List<String> hvals(String key) {
        try (Jedis jedis = getJedis()) {
            return jedis.hvals(key);
        } catch (Exception e) {
            logger.error("redis hvals error", e);
            return null;
        }
    }

    public static Set<Tuple> zrangeByScoreWithScores(String key, double min, double max) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrangeByScoreWithScores(key, min, max);
        } catch (Exception e) {
            logger.error("redis zrangeByScoreWithScores error", e);
            return null;
        }
    }
    public static Set<Tuple> zrangeByScoreWithScoresLimit(String key, double min, double max, int offset, int count) {
        try (Jedis jedis = getJedis()){
            return jedis.zrangeByScoreWithScores(key, min, max, offset, count);
        } catch (Exception e) {
            logger.error("redis zrangeByScoreWithScoresLimit error", e);
            return null;
        }
    }

    public static Set<Tuple> zrevrangeByScoreWithScores(String key, int max, int min) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrevrangeByScoreWithScores(key, max, min);
        } catch (Exception e) {
            logger.error("redis zrevrangeByScoreWithScores error", e);
            return null;
        }
    }

    public static Set<Tuple> zrevrangeByScoreWithScoresLimit(String key, double min, double max, int offset, int count) {
        try (Jedis jedis = getJedis()) {
            return jedis.zrevrangeByScoreWithScores(key, max, min, offset, count);
        } catch (Exception e) {
            logger.error("redis zrevrangeByScoreWithScoresLimit error", e);
            return null;
        }
    }
    public static List<String> zrange(String key, int start, int end) {
        List<String> returnSet = Lists.newArrayList();
        try (Jedis jedis = getJedis()) {
            Set<String> set = jedis.zrange(key, start, end);
            for (String s : set) {
                returnSet.add(s);
            }
        } catch (Exception e) {
            logger.error("redis zrange error", e);
            return null;
        }
        return returnSet;
    }

    public static List<String> zrevrange(String key, int start, int end) {
        List<String> list = Lists.newArrayList();
        try (Jedis jedis = getJedis()) {
            Set<String> set = jedis.zrevrange(key, start, end);
            for (String s : set) {
                list.add(s);
            }
        } catch (Exception e) {
            logger.error("redis zrevrange error", e);
            return null;
        }
        return list;
    }
    /**
     * 根据key获取链表
     *
     * @param key
     * @param start
     * @param end
     * @return
     * @author LI JIA KUI
     * @date 2017年11月10日 上午6:03:14
     * @see [类、类#方法、类#成员]
     */
    public static List<String> lrange(String key, int start, int end) {
        try (Jedis jedis = getJedis()) {
            return jedis.lrange(key, start, end);
        } catch (Exception e) {
            logger.error("redis lrange error", e);
            return null;
        }
    }
}
